﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.IO;

namespace getPixelInformation
{
    class histogramEqualization
    {
        private Matrix map;
        private greyLevel Level;
        private double[] cumulativeTotal;
        private int n;
        private int h;
        private int w;

        public histogramEqualization()
        {
            this.n =  8;
            this.h = 0;
            this.w = 0;
            this.map = new Matrix();
            this.Level = new greyLevel(this.n);
            this.cumulativeTotal = new double[this.n];
        }

        public histogramEqualization(int n)
        {
            this.n = n;
            this.h = 0;
            this.w = 0;
            this.Level = new greyLevel(this.n);
            this.map = new Matrix();
            this.cumulativeTotal = new double[this.n];
        }

        public histogramEqualization(string filePath,int n)
        {
            Bitmap bm = new Bitmap(filePath);
            int zone = -1;

            this.n = n;
            
            this.h = bm.Height;
            this.w = bm.Width;

            this.map = new Matrix(h,w);
            this.Level = new greyLevel(this.n);
            this.cumulativeTotal = new double[this.n];


            for (int i = 0; i < h; i++)
            {
                for (int j = 0; j < w; j++)
                {
                    Color C = bm.GetPixel(j, i);
                    zone = this.detectedGreyZone(C.R) - 1;
                    //this.detectedGreyZone(255);
                    this.map.setValue(i, j, zone);
                    this.Level.setCountGreyLevel(zone, C.R);
                    //this.cumulativeTotal[zone]++;
                }
            }

            this.Level.updateRateElement();            
            for (int f = 0; f < this.n; f++)
            {
                this.cumulativeTotal[f] = this.Level.getElementRate(f);
            }
            bm.Dispose();
        }

        public histogramEqualization(histogramEqualization hE)
        {
            this.n = hE.n;
            this.h = hE.h;
            this.w = hE.w;
            this.map = new Matrix(hE.map);
            this.Level = new greyLevel(hE.Level);
            for (int i = 0; i < this.n; i++)
            {
                this.cumulativeTotal[i] = hE.cumulativeTotal[i];
            }
        }

        public int detectedGreyZone(int value)
        {
            float range = (float)256 / this.n;
            int zone = -1;
            for (int i = 1; i <= this.n; i++)
            {
                float e = range * i;
                if ((value + 1) <= e)
                {
                    zone = i;
                    break;
                }
            }
            return zone;
        }

        public void doCumulativeTotal()
        {
            for (int i = 1; i < this.n; i++)
            {
                this.cumulativeTotal[i] += this.cumulativeTotal[i - 1];
            }
        }

        public void doReplacedTable()
        {
            for (int i = 0; i < this.n; i++)
            {
                this.cumulativeTotal[i] = Math.Round(this.cumulativeTotal[i] * (this.n - 1));
            }
        }

        public void updateGreyLevel()
        {
            for (int i = 0; i < this.n; i++)
            {
                this.Level.addNewCountGreyLevel((int)(this.cumulativeTotal[i]), this.Level.getValueCountTemp(i));
            }
            int e = this.Level.getCountFromValue(3);
        }

        public void doHistogramEqualization(string filePath)
        {
            this.doCumulativeTotal();
            this.doReplacedTable();
            this.updateGreyLevel();
            this.Level.updateRateElementFormer();

            Bitmap newGreyScale = new Bitmap(this.w, this.h);
            Bitmap bm = new Bitmap(filePath);

            for (int i = 0; i < h; i++)
            {
                for (int j = 0; j < w; j++)
                {
                    int zone = map.getValue(i, j);
                    double value = this.cumulativeTotal[zone];
                    int GS  = -1;
                    if (value == zone)
                    {
                        Color C = bm.GetPixel(j, i);
                        GS = C.R;
                    }
                    else
                    {
                        GS = (int)(Math.Round(value * (256 / this.n)));
                    }

                    Color greyScaleColor = Color.FromArgb(GS, GS, GS);
                    newGreyScale.SetPixel(j, i, greyScaleColor);
                }
            }
            string str = Path.GetDirectoryName(filePath);
            newGreyScale.Save(str + "//newGreyScalePicture.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
            newGreyScale.Dispose();
        }
    }
}
